import { DatabaseType } from '../types/database.js';
import {
  Config,
  AppConfig,
  AuthConfig,
  LogConfig,
  DatabaseConfig,
  RedisConfig,
  RememberConfig,
  SwaggerConfig,
} from '../types/config.js';
import { LogLevel } from '../types/logger.js';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

// 获取当前文件的目录路径
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const rootDir = path.join(__dirname, '..', '..');

// 获取当前环境
const nodeEnv = process.env.NODE_ENV || 'development';

/**
 * 一个强化版的环境变量加载函数，处理编码问题
 * @param filePath 环境变量文件路径
 * @returns 加载状态及变量
 */
function loadEnvFile(filePath: string): { success: boolean; vars: Record<string, string> } {
  if (!fs.existsSync(filePath)) {
    return { success: false, vars: {} };
  }

  try {
    // 以二进制方式读取，处理可能的BOM
    const buffer = fs.readFileSync(filePath);

    // 检测和删除BOM
    let content: string;
    if (buffer.length >= 3 && buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) {
      // UTF-8 with BOM
      content = buffer.toString('utf8', 3);
      console.log(`文件 ${path.basename(filePath)} 包含 UTF-8 BOM，已移除`);
    } else {
      // 没有BOM
      content = buffer.toString('utf8');
    }

    // 手动解析环境变量
    const vars: Record<string, string> = {};
    content.split('\n').forEach(line => {
      const trimmedLine = line.trim();
      if (trimmedLine && !trimmedLine.startsWith('#')) {
        // 匹配键值对
        const match = trimmedLine.match(/^([^=]+)=(.*)$/);

        if (match) {
          const key = match[1].trim();
          let value = match[2].trim();

          // 去掉可能的引号
          value = value.replace(/^["']|["']$/g, '');

          vars[key] = value;

          // 设置到process.env
          process.env[key] = value;
        }
      }
    });

    return { success: true, vars };
  } catch (error) {
    console.error(`读取文件 ${filePath} 时出错:`, error);
    return { success: false, vars: {} };
  }
}

/**
 * 按优先级加载环境变量文件
 * 加载顺序从低到高（后加载的会覆盖先加载的）:
 * 1. .env - 基础配置，所有环境共享（优先级最低）
 * 2. .env.local - 本地覆盖配置（除测试环境外）
 * 3. .env.[NODE_ENV] - 特定环境配置（如 .env.production）
 * 4. .env.[NODE_ENV].local - 特定环境本地覆盖配置（优先级最高）
 *
 * 例如:
 * - 如果同一个变量在 .env 和 .env.production 中都定义了，将使用 .env.production 中的值
 * - 如果同一个变量在 .env.production 和 .env.production.local 中都定义了，将使用 .env.production.local 中的值
 */
function loadEnvFiles() {
  const envFiles = [
    path.resolve(rootDir, '.env'), // 基础配置（优先级最低）
    nodeEnv !== 'test' ? path.resolve(rootDir, '.env.local') : null, // 本地覆盖（测试环境跳过）
    path.resolve(rootDir, `.env.${nodeEnv}`), // 环境特定配置
    path.resolve(rootDir, `.env.${nodeEnv}.local`), // 环境特定本地覆盖（优先级最高）
  ].filter(Boolean) as string[];

  const loadedFiles = [];

  // 按顺序加载环境文件，后加载的会覆盖先加载的
  for (const filePath of envFiles) {
    const result = loadEnvFile(filePath);
    if (result.success) {
      loadedFiles.push(path.basename(filePath));
      console.log(`load files ${filePath} ,env is ${JSON.stringify(result.vars)}`);
    }
  }

  // 记录已加载的环境文件
  if (loadedFiles.length > 0) {
    console.log(`已加载环境文件: ${loadedFiles.join(', ')}`);
  } else {
    console.warn('警告: 未找到任何环境文件');
  }
}

// 加载环境文件
loadEnvFiles();

/**
 * 从环境变量获取值，支持默认值
 * @param key 环境变量键
 * @param defaultValue 默认值
 * @returns 环境变量值或默认值
 */
function getEnv(key: string, defaultValue: string = ''): string {
  return process.env[key] || defaultValue;
}

/**
 * 从环境变量获取数值，支持默认值
 * @param key 环境变量键
 * @param defaultValue 默认数值
 * @returns 环境变量数值或默认数值
 */
function getEnvNumber(key: string, defaultValue: number): number {
  const value = process.env[key];
  if (value === undefined) {
    return defaultValue;
  }
  const num = parseInt(value, 10);
  return isNaN(num) ? defaultValue : num;
}

/**
 * 从环境变量获取布尔值，支持默认值
 * @param key 环境变量键
 * @param defaultValue 默认布尔值
 * @returns 环境变量布尔值或默认布尔值
 */
function getEnvBoolean(key: string, defaultValue: boolean): boolean {
  const value = process.env[key]?.toLowerCase();
  if (value === undefined) {
    return defaultValue;
  }
  return value === 'true' || value === '1' || value === 'yes';
}

// 配置加载及验证函数
function loadConfig(): Config {
  // 应用配置
  const app: AppConfig = {
    port: getEnvNumber('PORT', 3000),
    nodeEnv: getEnv('NODE_ENV', 'development'),
    isProd: getEnv('NODE_ENV', 'development') === 'production',
    jwtSecret: getEnv('JWT_SECRET', 'your-secret-key'),
    uploadDir: path.join(rootDir, 'uploads'),
    aesKey: getEnv('AES_KEY', 'Shif0ne@Product~'),
    aesIv: getEnv('AES_IV', 'ZYpq%kVPSYH8h@1q'),
    secretKey: getEnv('SECRET_KEY', 'Shif0ne@Product~'),
    secretIv: getEnv('SECRET_IV', 'ZYpq%kVPSYH8h@1q'),
    saveLogs: getEnvBoolean('SAVE_LOGS', false),
    useCaptcha: getEnvBoolean('CAPTCHA_ENABLED', false),
  };

  const remember: RememberConfig = {
    enabled: getEnvBoolean('REMEMBER_ENABLED', false),
    cookieKey: getEnv('REMEMBER_KEY', 'REMEMBER_ID'),
    expired: getEnvNumber('REMEMBER_EXPIRED', 7 * 24 * 60 * 60 * 1000),
  };

  // 数据库配置
  const db: DatabaseConfig = {
    type:
      getEnv('DB_TYPE', 'mysql').toLowerCase() === 'postgres'
        ? DatabaseType.POSTGRES
        : DatabaseType.MYSQL,
    mysql: {
      host: getEnv('MYSQL_HOST', 'localhost'),
      port: getEnvNumber('MYSQL_PORT', 3306),
      user: getEnv('MYSQL_USER', 'root'),
      password: getEnv('MYSQL_PASSWORD', ''),
      database: getEnv('MYSQL_DATABASE', 'test'),
      waitForConnections: true,
      connectionLimit: 10,
      queueLimit: 0,
    },
    postgres: {
      host: getEnv('POSTGRES_HOST', 'localhost'),
      port: getEnvNumber('POSTGRES_PORT', 5432),
      user: getEnv('POSTGRES_USER', 'postgres'),
      password: getEnv('POSTGRES_PASSWORD', ''),
      database: getEnv('POSTGRES_DATABASE', 'test'),
      max: 20,
      idleTimeoutMillis: 30000,
      connectionTimeoutMillis: 2000,
    },
  };

  // Redis 配置
  const redis: RedisConfig = {
    host: getEnv('REDIS_HOST', 'localhost'),
    port: getEnvNumber('REDIS_PORT', 6379),
    password: getEnv('REDIS_PASSWORD', ''),
    db: getEnvNumber('REDIS_DB', 0),
  };

  // 确保日志级别是有效的LogLevel类型
  function isValidLogLevel(level: string): level is LogLevel {
    return ['trace', 'debug', 'info', 'warn', 'error', 'fatal'].includes(level);
  }

  // 日志配置
  const logLevel = getEnv('LOG_LEVEL', 'info');
  const level: LogLevel = isValidLogLevel(logLevel) ? logLevel : 'info';

  const log: LogConfig = {
    level,
    dir: getEnv('LOG_DIR', 'logs'),
  };

  // 认证配置
  const auth: AuthConfig = {
    whitelist: ['/login'],
    session: {
      key: 'koa:sess',
      maxAge: 24 * 60 * 60 * 1000, // 24小时
      httpOnly: true,
      signed: false,
      rolling: true,
    },
  };

  // Swagger配置
  const swagger: SwaggerConfig = {
    enabled: getEnvBoolean('SWAGGER_ENABLED', !app.isProd),
    title: getEnv('SWAGGER_TITLE', 'Koa Multi-DB API'),
    description: getEnv('SWAGGER_DESCRIPTION', 'Koa.js application with multiple database support'),
    version: getEnv('SWAGGER_VERSION', '1.0.0'),
    path: getEnv('SWAGGER_PATH', '/api-docs'),
    host: getEnv('SWAGGER_HOST', ''),
    basePath: getEnv('SWAGGER_BASE_PATH', '/'),
    schemes: getEnv('SWAGGER_SCHEMES', 'http,https').split(','),
  };

  return {
    app,
    db,
    redis,
    log,
    auth,
    remember,
    swagger,
  };
}

// 导出配置对象
export const config = loadConfig();
